Vector Store
RDBとの違い
https://scrapbox.io/files/6584f953c828320022fc623e.png
検索して必要なデータを取り出すことを目的としています。
ただ、一般的なデータベース(いわゆるRDBなど)とは異なり貯めこむデータがベクトルデータとなり それに付随して様々な違いがあります。
そしてこのベクトルデータベースは、LLMとは非常に相性がいいです。 LLMでは文章はベクトルに変換して処理するからです。
文章や単語はテキストデータの状態では統計関数に入力することができないため
必ず量的データに変換する必要があり、それがベクトルデータということになります。
https://scrapbox.io/files/65615f086f48e1001b9074a4.png
文章をどうやってベクトルに変換するのか?
それはEmbeddingと呼ばれる処理を行うことで変換が可能になります。
このEmbedding自体もLLMの機能で行いますし、Embeddingの処理だけを対象としたLLMなども世の中には沢山あります。
上図のように
Embeddingの処理によって文章がベクトルに変換されるので計算することができるようになります。
※Embeddingに使うモデルはOpenAIだけではありません。その他のLLMプロバイダーやオープンソースのLLMも十分に使えます。
ここでの本質は
このベクトルの値がどのように決まるのか?
どういったロジックでベクトルに変換されるのか?
https://scrapbox.io/files/65615f81cddbba001ca3abb0.png
これは単純な四則演算の例ですが
LLMの推論処理やベクトルストアでのセマンティック検索
類似検索でも要領は同じです。
これらは統計処理のようなもっと高度な演算処理を行います。
「ベクトル化」ではなく「埋め込み」と呼ぶ理由
Embedの処理は「埋め込み」、「埋め込みベクトル」、「埋め込み表現」
https://scrapbox.io/files/65615f2baa881c001c734e92.png
上述の二次元の意味空間は、各単語の属性のようなものをベースに近しいベクトルになるように筆者が適当に絵を書いたもの
この中の、例えば、「富士山」という単語は「山」という意味合いを持ちますから
他の山と近しいベクトルの絵にしました
ですが、「富士山が位置する国は日本」という意味合いにおいては「日本」という単語のベクトルのほうに最も近くないといけないはず。
そして、「富士山は日本で標高が一番高い」という意味合いにおいては「一番」という単語のベクトルと一番近くなければいけないはずです。
このように単語は文脈の中で様々な意味をもちますので、実際は例示したような二次元ではとても表すことができず、現在市場に出回っているLLMのEmbedモデルはだいたい753次元~2048次元という高次元のベクトルを生成するものが主流です。
つまり、単語や文章をEmbedすると、下図のように、それらはLLMが事前学習した高次元の意味空間に埋め込まれるようなイメージが理解しやすいのではないかなと思います。
https://scrapbox.io/files/65615ffb0ae505001cb6ba4b.png
このようにして、文章データを変換したベクトルを大量にベクトルデータベースにため込んで検索ができるようにします。
RDBでは貯め込んだデータを検索するためにクエリを実行しますが ベクトルデータベースの検索処理とはセマンティック検索ということになります。
セマンティクスとは日本語で「意味論」を指し、セマンティック検索とはRDBのような単に検索キーワードの一致による検索ではなく
そのキーワードが持つ意味を考慮した検索を行うということです
文章データをベクトルデータに変換(意味空間にマッピングする)ことにより実現する機構です。
ベクトルデータベースのセマンティック検索、類似度検索
https://scrapbox.io/files/65616050017f33001ca70815.png
例えば
先ほどの二次元の意味空間を持ったベクトルデータベースに「東京」というトークンで検索した場合を考えてみます。
RDBではname列の「東京」という文字が一致した行を検索しその結果が得られることがわかります。
これは単純に「東京」というキーワードが部分一致しているかどうかだけで検索をしているという状況です。
それに対してベクトルデータベースでは上述したように「東京」という単語が持つ意味を考慮したクエリ結果が得られるイメージです。
「東京」という単語は日本の首都であり、都市であり、高層ビルが立ち並ぶエリア、という様々な意味合いがあります。
これら意味合いの近い単語がベクトルデータベースに保存されている場合
セマンティック検索によって、これら近い単語の検索が可能になります。
ベクトルデータベースではどのようにベクトルの類似度を計算しているのか
Embeddingの処理では似た意味をもつ単語は近しい値のベクトル値が割り当てられます。
したがって、セマンティック検索をすることによって、そのベクトル値がどれくらい近い値なのかを計算し、意味合いの似た単語を検索することができるようになります。
この際、ベクトル値が近いとは具体的にどういう状況を意味するのか?
私達は高校の代数・幾何学の授業でベクトルとは「向き」と「大きさ」を持つ量的データと習ったはずです。
まあ実際には「量的データ」という単語は使っていなかったとしても「ベクトルとは向きと大きさ」と学習したはず。
ということは、ベクトルの「向き」と「大きさ」を計算しさえすればベクトルの類似度を測れるということになり
ひいては意味の近い単語を検索しているということになるわけです。
この向きと大きさの計算に使われる計算手法が以下のようなものです。
ベクトルの「向き」
ベクトルの「大きさ」
https://scrapbox.io/files/656160b26eb898001b6f6b7b.png
コサイン類似度やドット積
ベクトルの内角に関係する計算をしている
内角が小さいほど似たような「向き」となり、近しいベクトルとなる
ベクトル(行列)の内積をベースに計算
ユークリッド距離
ベクトルが示す2点間の直線距離を測る計算をしている
距離が近いほど似たような「大きさ」となり、近しいベクトルとなる
ピタゴラスの定理から計算
ベクトルデータベースで行われるベクトル演算の効率化
ただし、シンプルな演算処理とは言え
クエリの度にベクトルデータベース内の全てのベクトルとの行列演算をするのは非常に非効率です。
RDBに例えるとクエリを実行した際に全表捜索が実行されてしまうイメージ
RDBではそうならないようにするためにパーティショニングや、索引を作りますよね。
ベクトルデータベースでも似たようなことをしています。
それは、膨大な数のベクトルデータを、値の近しい集団に分類して、グループ単位で処理することにより演算処理を効率化するというものです。
https://scrapbox.io/files/656161020a6cc4001bcdc14b.png
この分類処理には古典機械学習でお馴染みの最近傍法が使われてるケースが多いです。
k近傍法(KNN)や近似最近傍法(ANN)などです。
そのため、大抵のベクトルデータベースではこれらのアルゴリズムが実装されていたり、プラグインなどで追加できるようになっています。
世の中には沢山のベクトルストアがあり、特に最新のものは大変興味をそそられます。
ですが、筆者が普段対面する顧客はどちらかというと
Elasticsearchのような古参で実績のある技術を好む傾向があり
それらの顧客が運用しているElasticsearchの中には既に大量のドキュメントがベクトル化されため込まれている場合があります。
そのため、今回はベクトルストアとしてElasticsearchを使ってみたいと思います。
Oracle CloudではMarketplaceにElasticsearchがあり、ボタンクリック数回でElasticsearchの分散処理環境が構築できますので是非お試しください。本記事でもこの環境を使っています。